(function(global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('underscore')) :
    typeof define === 'function' && define.amd ? define(['underscore'], factory) :
    global.hauto = factory(_);
}(this, function(_) {
  'use strict';

  function auto(vtemple, inum) {
    if (inum != null && _.isNumber(inum) && inum > 1) {
      var aset = [];
      for (var i = 0; i < inum; i++)
        aset.push(genData(vtemple));
      return aset;
    } else {
      return genData(vtemple);
    }
  }

  function genData(vtemple) {
    if (_.isArray(vtemple))
      return genArray(vtemple);
    else if (_.isObject(vtemple))
      return genObject(vtemple);
    else if (_.isFunction(vtemple))
      return genFunction(vtemple);
    else if (_.isNumber(vtemple))
      return genNumber(vtemple);
    else if (_.isString(vtemple))
      return genString(vtemple);
    else
      return vtemple;
  }


  function genArray(a) {
    var aset = [];
    for (var i = 0; i < a.length; i++)
      aset.push(genData(a[i]));
    return aset;
  }

  function genObject(o) {
    var oset = {};
    for (var param in o)
      oset[param] = genData(o[param]);
    return oset;
  }

  function genFunction(f) {
    return f();
  }

  function genNumber(i) {
    return _.random(i - 30, i + 30);
  }

  function genString(s) {
    if (s.indexOf("$") == 0)
      return genSpecialData(s);
    else
      return randomString(null, s.length);
  }

  function randomString(str, isize) {
    var res = "";
    var schar = str || "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var charLen = schar.length;
    for (var i = 0; i < isize; i++) {
      var index = Math.round(Math.random() * (charLen - 1));
      res += schar.charAt(index);
    }
    return res;
  }

  function cut(str, isize) {
    var atip = [];
    var icount = Math.ceil(str.length / isize);
    for (var i = 0; i < icount; i++)
      atip.push(str.substr(i * isize, isize));
    return atip;
  }

  function genIp(shex) {
    var s1 = shex ? shex : randomString("0123456789ABCDEF", 8);
    var s = parseInt(s1, 16).toString(2);
    /**
     * fill "0" when length less than 32
     */
    if (s.length < 32) {
      var k = 32 - s.length;
      var stmp = "";
      for (var i = 0; i < k; i++)
        stmp += "0";
      s = stmp + s;
    }
    var aipCut = cut(s, 8);
    var aipCutTmp = [];
    for (var i = 0; i < aipCut.length; i++)
      aipCutTmp[i] = parseInt(aipCut[i], 2).toString();
    aipCut = null;
    return aipCutTmp.join(".");
  }

  function genMac(split) {
    var arr = [];
    for (var i = 0; i < 6; i++)
      arr.push(randomString("0123456789ABCDEF", 2));
    return arr.join(split || ":");
  }

  function genChinese(shex) {
    var s = (shex ? shex : "\\u" + (parseInt("4e00", 16) + _.random(0, 20901)).toString(16));

    var s2 = unescape(s.replace(/\\u([0-9a-zA-Z]{4})/g, "%u$1"));
    return s2;
  }

  function genSpecialData(sexpression) {
    var result;
    if ((result = /^\$mac$/.exec(sexpression)) != null) {
      return genMac();
    } else if ((result = /^\$ip$/.exec(sexpression)) != null) {
      return genIp();
    } else if ((result = /^\$mobile$/.exec(sexpression)) != null) {
      return "151" + randomString('0123456789', 8);
    } else if ((result = /^\$email$/.exec(sexpression)) != null) {
      return randomString("abcdefghijklmnopqrstuvwxyz", 1) + randomString(null, 8) + "@hotmail.com";
    } else if ((result = /^\$int, *(-?[0-9]|-?[1-9][0-9]+) *, *(-?[0-9]|-?[1-9][0-9]+) *$/.exec(sexpression)) != null) {
      var min = parseInt(result[1]);
      var max = parseInt(result[2]);
      return _.random(min, max);
    }
    if ((result = /^\$float, *(-?[0-9]+\.?[0-9]*) *, *(-?[0-9]+\.?[0-9]*) *$/.exec(sexpression)) != null) {
      var min = parseFloat(result[1]);
      var max = parseFloat(result[2]);
      return _.random(min, max);
    } else if ((result = /^\$timestamp, *([0-9]+) *$/.exec(sexpression)) != null) {
      var interval = parseInt(result[1]);
      var now = Math.round(new Date().getTime() / 1000);
      return _.random(now - interval, now + interval);
    } else if ((result = /^\$ms, *([0-9]+) *$/.exec(sexpression)) != null) {
      var interval = parseInt(result[1]);
      var now = Math.round(new Date().getTime());
      return _.random(now - interval * 1000, now + interval * 1000);
    } else if ((result = /^\$chinese, *([0-9]+) *$/.exec(sexpression)) != null) {
      var count = parseInt(result[1]);
      var c = "";
      for (var i = 0; i < count; i++)
        c += genChinese();
      return c;
    } else
      return "error expression";
  }

  return auto;

}))
